package org.az.netty_study.p01_nio组件之buffer;

import org.az.netty_study.ByteBufferUtil;

import java.nio.ByteBuffer;

/**
 * 网络上有多条数据发送给服务器段，数据之间以\n分割
 *  1.hello,world\n
 *  2.How are you?\n
 *  3.I'm fine,thinks,and you?\n
 * 但是由于某些原因，这些数据在被接受时，被重新组合，比如变成了:
 *  1.hello,world\nHow are you?\nI'm f  (黏包，发送方为了效率先进行了数据合并，再一块发送)
 *  2.ine,thinks,and you?\n     (半包，服务器缓冲区大小限制，不能一次性接受发送过来的全部数据，就先接受一部分(黏包)，再接受剩下的(半包))
 * 现在要求将这些黏包数据和半包数据重新恢复成三条原始数据
 */
public class _8_黏包和半包 {
    public static void main(String[] args) {
        ByteBuffer source = ByteBuffer.allocate(30);
        //模拟黏包
        source.put("hello,world\nHow are you?\nI'm f".getBytes());
        split(source);
        //模拟半包
        source.put("ine,thinks,and you?\n".getBytes());
        split(source);
    }

    /**
     * @param source
     */
    static void split(ByteBuffer source) {
        //进行拆分前，切换读模式
        source.flip();
        for (int i = 0; i < source.limit(); i++) {
            //换行符是一个字节，找到换行符，表示前面的数据是完整的数据.get(int)不会改变position
            if (source.get(i) == '\n') {
                //把完整消息存入新的ByteBuffer,i是换行符的索引
                int length = i - source.position() + 1;
                ByteBuffer target = ByteBuffer.allocate(length);
                for (int j = 0; j < length; j++) {
                    //get()会改变position
                    target.put(source.get());
                }
                ByteBufferUtil.debugAll(target);
            }
        }
        //没读完的数据，就是半包，留取都下一次接着读
        //拆分结束，接收剩下的数据要切换到写模式
        source.compact();
    }
}
